      SUBROUTINE NAE ( NREAD, NWRITE, NUM, MAX, IARRAY, ERROR )
C*
C*                  *******************************
C*                  *******************************
C*                  **                           **
C*                  **          NAE              **
C*                  **                           **
C*                  *******************************
C*                  *******************************
C*
C*     SUBPROGRAM :
C*          NIFTY ARRAY EDITOR
C*
C*     AUTHOR :
C*          ART RAGOSTA
C*          MS 207-5
C*          AMES RESEARCH CENTER
C*          MOFFETT FIELD, CALIF  94035
C*          (415) 694-5578
C*
C*     PURPOSE :
C*          TO ENABLE THE SCREEN-ORIENTED EDITING OF 1 TO 3 ARRAYS.
C*
C*     METHODOLOGY :
C*          USES DEC RUN TIME LIBRARY CALLS FOR SCREEN MANIPULATION.
C*
C*     INPUT ARGUMENTS :
C*          NREAD  - KEYBOARD LOGICAL UNIT NUMBER.
C*          NWRITE - SCREEN LOGICAL UNIT NUMBER.
C*          NUM    - NUMBER OF ELEMENTS IN ARRAYS.
C*          MAX    - THE DIMENSION OF ARRAYS.
C*          IARRAY - THE FIRST DATA ARRAY.
C*
C*     OUTPUT ARGUMENTS :
C*          ERROR  - .TRUE. IF AN UNRECOVERABLE ERROR WAS ENCOUNTERED.
C*
C*     INTERNAL WORK AREAS :
C*          STRING - TEMPORARY STORAGE FOR INPUT STRING.
C*
C*     COMMON BLOCKS :
C*          NONE
C*
C*     FILE REFERENCES :
C*          NREAD, NWRITE
C*
C*     DATA BASE ACCESS :
C*          NONE
C*
C*     SUBPROGRAM REFERENCES :
C*          CLEAR,  NSTAT,  WRITA,  GOTOXY,  CAPS,   LEFT,  MBELL
C*          STAT,   WAIT,   WRITL,  REVLF,   GETOKE, RIGHT, SRESET
C*
C*     ERROR PROCESSING :
C*          CHECK FOR VALID COMMANDS.
C*          CHECK FOR RIGHT NUMBER OF ENTRIES ON A LINE.
C*
C*     TRANSPORTABILITY LIMITATIONS :
C*          NOT TRANSPORTABLE.
C*
C*     ASSUMPTIONS AND RESTRICTIONS :
C*          VT-100 COMPATIBLE TERMINALS ONLY.
C*
C*     LANGUAGE AND COMPILER :
C*          ANSI FORTRAN 77
C*
C*     VERSION AND DATE :
C*          VERSION I.0      4-FEB-85
C*
C*     CHANGE HISTORY :
C*           4-FEB-85    INITIAL VERSION
C*
C***********************************************************************
C*
      CHARACTER *80 STRING
      CHARACTER *20 TOKE
      CHARACTER *1 ESC, TYPE
      LOGICAL ERROR, DOWN, ERR
      DIMENSION IARRAY(MAX)
      DATA ESC/27/
C
C  NUM    - THE NUMBER OF ELEMENTS IN IARRAY
C  MAX    - THE MAXIMUM DIMENSION OF IARRAY
C  IARRAY - THE DATA TO BE EDITED
C  NARRAY - THE NUMBER OF ARRAYS ( 1 FOR THIS VERSION )
C  ERROR  - INTERNAL ERROR FLAG
C  DOWN   - .TRUE. IF THE DEFAULT DIRECTION IS DOWN
C  IPTR   - THE ARRAY ELEMENT WE ARE PRESENTLY POINTING TO
C  IX     - X LOCATION OF CURSOR (ALWAYS 1 IN PRESENT VERSION)
C  IY     - Y LOCATION OF CURSOR (BETWEEN 2 AND 24)
C  NREAD  - KEYBOARD UNIT NUMBER
C  NWRITE - SCREEN UNIT NUMBER
C  STRING - INPUT BUFFER
C  ISTART - THE FIRST ELEMENT IN THE ARRAY TO BE DISPLAYED ON THE SCREEN
C
      GO TO 50
      ENTRY NAE1 ( NREAD, NWRITE, NUM, MAX, IARRAY, ERROR )
50    CALL CLEAR
      ERROR  = .FALSE.
      IF ( NUM .GT. MAX ) THEN
         ERROR = .TRUE.
         RETURN
      ENDIF
      NARRAY = 1
      DOWN   = .TRUE.
      IX     = 1
      IY     = 2
C
C --- DISPLAY INITIAL STATUS, DISPLAY FIRST PART OF ARRAYS
C
      IPTR = 0
      IF ( NUM .GE. 1 ) IPTR = 1
      ISTART = IPTR
      CALL NSTAT ( IX, IY, NUM, DOWN )
      CALL WRITA ( NWRITE, NUM, IARRAY, ISTART )
      CALL GOTOXY ( NWRITE, IX, IY )
C
C --- REPEAT UNTIL DONE
C
100   READ ( NREAD, 900, END=1000, ERR=1000 ) STRING
      CALL CAPS ( STRING )
      CALL LEFT ( STRING )
      IF (STRING(1:1) .EQ. 'A') THEN
C
C ----- 'ADD' COMMAND
C
         IF (NUM .EQ. MAX) THEN
            CALL MBELL ( NWRITE )
            CALL STAT ( IX, IY, ' Arrays full, insert ignored. ' )
            CALL WAIT ( 3 )
            CALL NSTAT ( IX, IY, NUM, DOWN )
         ELSE
            IARRAY(NUM+1) = 0
            NUM    = NUM + 1
            CALL NSTAT ( IX, IY, NUM, DOWN )
            ISTART = MAX0(NUM-21,1)
            IF (NUM .EQ. 0 )ISTART = 0
            CALL WRITA ( NWRITE, NUM, IARRAY, ISTART )
            IPTR   = NUM
            IY     = MIN0 ( NUM+1, 23 )
            IF (NUM .EQ. 0) IY = 2
            CALL GOTOXY ( NWRITE, IX, IY )
         ENDIF
      ELSE IF (STRING(1:1) .EQ. 'B') THEN
C
C ----- 'BEGIN' COMMAND
C
         IPTR   = 0
         IF (NUM .GE. 1) IPTR = 1
         ISTART = IPTR
         CALL WRITA ( NWRITE, NUM, IARRAY, ISTART )
         IY     = 2
         CALL GOTOXY ( NWRITE, IX, IY )
C
      ELSE IF (STRING(1:1) .EQ. 'D') THEN
C
C ----- 'DELETE' COMMAND
C
         IF (NUM .GT. 0) THEN
            NUM = NUM - 1
            IF (IPTR .EQ. NUM+1) THEN
               IPTR = NUM
               ISTART = ISTART - 1
               IF ( ISTART .LE. 0 ) THEN
                  ISTART = 1
                  IY = IY - 1
               ENDIF
            ELSE
               DO 110 II = IPTR, NUM
                  IARRAY(II) = IARRAY(II+1)
110               CONTINUE
               IF ( ISTART+22 .GT. NUM )ISTART = ISTART - 1
               IF ( ISTART .LE. 0 )ISTART = 1
            ENDIF
            IF (NUM .EQ. 0) THEN
               ISTART = 0
               IY = 2
            ENDIF
            CALL NSTAT ( IX, IY, NUM, DOWN )
            CALL WRITA ( NWRITE, NUM, IARRAY, ISTART )
         ENDIF
         CALL GOTOXY ( NWRITE, IX, IY )
C
      ELSE IF (STRING(1:1) .EQ. 'E') THEN
C
C ----- 'END' COMMAND
C
         ISTART = NUM - 21
         IF (ISTART .LE. 0)ISTART = 1
         IF (NUM .EQ. 0 )ISTART = 0
         CALL WRITA ( NWRITE, NUM, IARRAY, ISTART )
         IPTR = NUM
         IY = MIN0 ( NUM+1, 23 )
         IF (NUM .EQ. 0) IY = 2
         CALL GOTOXY ( NWRITE, IX, IY )
C
      ELSE IF (STRING(1:1) .EQ. 'I') THEN
C
C ----- 'INSERT' COMMAND
C
         IF (NUM .EQ. MAX) THEN
            CALL MBELL ( NWRITE )
            CALL STAT ( IX, IY, ' Arrays full, insert ignored. ' )
            CALL WAIT ( 3 )
            CALL NSTAT ( IX, IY, NUM, DOWN )
         ELSE
            IF (IPTR .LE. NUM) THEN
               DO 120 II = NUM, IPTR, -1
                  IARRAY(II+1) = IARRAY(II)
120               CONTINUE
               IARRAY(IPTR) = 0
            ELSE
               IARRAY(NUM+1) = 0
            ENDIF
            NUM = NUM + 1
            CALL NSTAT ( IX, IY, NUM, DOWN )
            CALL WRITA ( NWRITE, NUM, IARRAY, ISTART )
            CALL GOTOXY ( NWRITE, IX, IY )
         ENDIF
C
      ELSE IF (STRING(1:1) .EQ. 'Q') THEN
         GO TO 1000
C
      ELSE IF (STRING(1:1) .EQ. 'R') THEN
C
C ----- 'REPAINT' SCREEN
C
         CALL WRITA ( NWRITE, NUM, IARRAY, ISTART )
         CALL GOTOXY ( NWRITE, IX, IY )
C
      ELSE IF (STRING(1:1) .EQ. 'S') THEN
C
C ----- 'SCROLL' DIRECTION TOGGLE
C
         DOWN = .NOT. DOWN
         CALL NSTAT ( IX, IY, NUM, DOWN )
         CALL GOTOXY ( NWRITE, IX, IY )
C
      ELSE IF ((STRING(1:1) .EQ. '?') .OR. (STRING(1:1) .EQ. 'H')) THEN
C
C ----- 'HELP' COMMAND
C
         CALL CLEAR
         WRITE ( NWRITE, 910 )
         READ ( NREAD, 920 )
         CALL CLEAR
         CALL NSTAT ( IX, IY, NUM, DOWN )
         CALL WRITA ( NWRITE, NUM, IARRAY, ISTART )
         CALL GOTOXY ( NWRITE, IX, IY )
      ELSE
C
C ----- INPUT LINE
C
         IF ( LENGTH(STRING) .EQ. 0 ) THEN
C
C -------- POSITION CURSOR ONLY
C
            IF ( DOWN ) THEN
               IF ( IPTR .LT. NUM ) THEN
                  IPTR = IPTR + 1
                  IY = IY + 1
                  IF ( IY .GT. 23 ) THEN
C
C  --------------  SCROLL UP
C
                     IY = 23
                     ISTART = ISTART + 1
                     CALL WRITL ( NWRITE, IY+1, IPTR, IARRAY )
                     WRITE ( NWRITE, 940 )
                     CALL REVLF ( NWRITE )
                  ENDIF
               ELSE
                  CALL REVLF ( NWRITE )
               ENDIF
            ELSE
               IF ( IPTR .GT. 1 ) THEN
                  IPTR = IPTR - 1
                  IY = IY - 1
                  IF (IY .LT. 2 ) THEN
C
C  --------------  DOWN SCROLL
C
                     IY = 2
                     ISTART = IPTR
                     CALL GOTOXY ( NWRITE, IX, IY )
                     WRITE ( NWRITE, 930 ) ESC
                     CALL WRITL ( NWRITE, IY, IPTR, IARRAY )
                  ENDIF
               ENDIF
               CALL GOTOXY ( NWRITE, IX, IY )
            ENDIF
         ELSE
C
C ------ MODIFY LINE
C
            IL = 1
            IA = 0
200         CALL GETOKE ( STRING, 80, IL, TOKE, TYPE, ERR )
            IF ( TYPE .EQ. 'E' ) THEN
               CALL WRITL ( NWRITE, IY, IPTR, IARRAY )
               GO TO 100
            ENDIF
            IF (( TYPE .NE. 'I' ) .OR. ERR ) THEN
               CALL MBELL ( NWRITE )
               CALL STAT ( IX, IY, ' Unintelligible input. ' )
               CALL WAIT ( 3 )
               CALL NSTAT ( IX, IY, NUM, DOWN )
               CALL WRITL ( NWRITE, IY, IPTR, IARRAY )
               GO TO 100
            ENDIF
            IA = IA + 1
            IF ( IA .GT. NARRAY ) THEN
               CALL MBELL ( NWRITE )
               CALL STAT ( IX, IY, ' Extra data on line ignored. ' )
               CALL WAIT ( 3 )
               CALL NSTAT ( IX, IY, NUM, DOWN )
               CALL WRITL ( NWRITE, IY, IPTR, IARRAY )
               GO TO 100
            ENDIF
C
C -------  PUT NEW VALUE IN ARRAY
C
            CALL RIGHT ( TOKE )
            READ ( TOKE, 950 ) IARRAY ( IPTR )
            GO TO 200
         ENDIF
      ENDIF
      GO TO 100
C
C --- END REPEAT UNTIL
C
1000  CALL SRESET ( NWRITE )
      CALL CLEAR
      RETURN
900   FORMAT ( A80 )
910   FORMAT (///,' A command is a line with a single letter on it :',/,
     $ '    A)dd     - add a blank line to the end of the arrays',/,
     $ '    B)egin   - go to the beginning of the arrays',/,
     $ '    D)elete  - delete the current line',/,
     $ '    E)nd     - go to the end of the arrays',/,
     $ '    I)nsert  - insert a line before the indicated line',/,
     $ '    Q)uit    - exit the editor',/,
     $ '    R)epaint - repaint the screen',/,
     $ '    S)croll  - change the direction of scrolling',/,
     $ '    ? - produce this message',///,
     $ ' Any other line is expected to be data.  Enter ^Z (control/Z)',
     $ /,'  to exit the editor.',//,
     $ ' Enter <CR> to continue.')
920   FORMAT ( A )
930   FORMAT ('+',A1,'M',$ )
940   FORMAT ( / )
950   FORMAT ( 10X,I10 )
      END
C
C---END NAE
C
